import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
import bcrypt from 'bcrypt';

import { UpdateUserDTO } from './dto/update-user.dto';
import { CreateUserDTO } from './dto/create-user.dto';
import { prisma } from '../../generated/prisma-client/sys';
import { QueryDTO } from 'src/common/dto/query.dto';
import { QueryPipe } from 'src/common/pipe/query.pipe';
import { UserInputError } from 'apollo-server';
import { Authorities } from 'src/common/decorator/authorities.decorator';

@Resolver('SysUser')
export class SysUserResolver {
  @Query('sysUsers')
  @Authorities('AUTH_SYS_USER_VIEW')
  async sysUsers(@Args('query', QueryPipe) { first, skip, orderBy }: QueryDTO) {
    const fragment = `
      fragment UsersWithRoles on SysUser {
        id
        username
        email
        mobile
        dateCreated
        dateUpdated
        roles {
          id
          description
        }
      }
    `;
    const items = await prisma
      .sysUsers({
        first,
        skip,
        orderBy,
      })
      .$fragment(fragment);
    const count: number = await prisma
      .sysUsersConnection()
      .aggregate()
      .count();

    return { items, count };
  }

  @Query('sysUser')
  async sysUser(
    @Args('id')
    id: string,
  ) {
    return await prisma.sysUser({ id });
  }

  @Mutation('createSysUser')
  @Authorities('AUTH_SYS_USER_CREATE')
  async createSysUser(
    @Args('user')
    { roleIds, ...data }: CreateUserDTO,
  ) {
    const tmp = await prisma.sysUser({ username: data.username });
    if (tmp) {
      throw new UserInputError('用户已存在！', { property: 'username' });
    }

    const cryptPass = await bcrypt.hash('123456', 10);
    return await prisma.createSysUser({
      password: cryptPass,
      ...data,
      roles: {
        connect: roleIds.map(id => ({
          id,
        })),
      },
    });
  }

  @Mutation('updateSysUser')
  @Authorities('AUTH_SYS_USER_UPDATE')
  async updateSysUser(
    @Args('user')
    { id, roleIds, ...data }: UpdateUserDTO,
  ) {
    return await prisma.updateSysUser({
      where: { id },
      data: {
        ...data,
        roles: {
          set: roleIds.map(item => ({
            id: item,
          })),
        },
      },
    });
  }

  @Mutation('deleteSysUsers')
  @Authorities('AUTH_SYS_USER_DELETE')
  async deleteSysUsers(
    @Args('ids')
    ids: string[],
  ) {
    return await prisma.deleteManySysUsers({ id_in: [...ids] });
  }
}
